﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EasyTrader.Manager
{
    public class HogaSquareOccSysManager : SysManager
    {

#region Member Variables
        private int m_TotalBuySquare = 0;
        public int TotalBuySquare
        {
            get { return m_TotalBuySquare; }
            set { m_TotalBuySquare = value; }
        }
        private int m_TotalSellSquare = 0;
        public int TotalSellSquare
        {
            get { return m_TotalSellSquare; }
            set { m_TotalSellSquare = value; }
        }

        private int m_TotalHogaSquare = 0;
        public int TotalHogaSquare
        {
            get { return m_TotalHogaSquare; }
            set { m_TotalHogaSquare = value; }
        }

        private int m_BuySquare = 0;
        public int BuySquare
        {
            get { return m_BuySquare; }
            set { m_BuySquare = value; }
        }
        private int m_SellSquare = 0;
        public int SellSquare
        {
            get { return m_SellSquare; }
            set { m_SellSquare = value; }
        }
        private int m_BuyTimeOcc = 0;
        public int BuyTimeOcc
        {
            get { return m_BuyTimeOcc; }
            set { m_BuyTimeOcc = value; }
        }
        private int m_SellTimeOcc = 0;
        public int SellTimeOcc
        {
            get { return m_SellTimeOcc; }
            set { m_SellTimeOcc = value; }
        }
#endregion
        // 이 함수는 현재 상태가 상승인지 하락인지 판단을 한다. 새로운 상태가 나오면 새로운 상태를 등록한다.
        // 호가 정점에서 평균값으로 일정개수를 내려오면 상태를 전환시켜 준다.
        private void FindCurState()
        {
            //return m_TotalSigMan.FindState(m_SysType, m_FirstSig, m_PriceStateList, m_LogFileName, ref m_CurState);

            // 시스템 상태를 확인한다.
            EasyTrader.Signal.PriceSignal curState = FindSysState();
            // 시스템 상태가 바뀌었을 경우 확인하고 신호정보를 복사하여 추가한다.
            m_TotalSigMan.CheckAddState(m_TotalSigMan.CurIndex, m_PriceStateList, curState);
        }

        private EasyTrader.Signal.PriceSignal FindSysState()
        {
            EasyTrader.Signal.PriceSignal lastState = m_TotalSigMan.GetLastSignal(m_PriceStateList);
            double curVal = m_TotalSigMan.CurVal;
            if (curVal == 0.0)
                return null;

            double dayAmp = m_TotalSigMan.GetDayAmp();
            // 현재 파동을 가져온다.
            EasyTrader.Wave.PriceWave curWave = m_TotalSigMan.ETWaveSignalManager.EasyTraderWaveManager.GetCurWave(m_TotalSigMan.CurIndex);
            if (curWave == null)
                return null;

            m_TotalSigMan.ETHogaSignalManager.GetBuySellSquare(m_TotalSigMan.CurIndex, ref m_BuySquare, ref m_SellSquare);
            m_TotalSigMan.ETHogaSignalManager.GetTotalBuySellSquare(m_TotalSigMan.CurIndex, ref m_TotalBuySquare, ref m_TotalSellSquare, ref m_TotalHogaSquare);

            double totalSquare = m_TotalHogaSquare;
            double buyRatio = 0.0;
            double sellRatio = 0.0;
            if (totalSquare != 0)
            {
                buyRatio = (Convert.ToDouble(totalSquare - m_TotalSellSquare) / totalSquare);
                sellRatio = (Convert.ToDouble(totalSquare - m_TotalBuySquare) / totalSquare);
            }

            if (lastState == null)
            {
                // 9시 30 초 이전에는 신호를 받지 않게 한다.
                int curTime = 0;
                if (GlobalVar.OperationMode == GlobalVar.OperationModeNormal)
                {
                    curTime = GlobalVar.TimeToIntEx();
                }
                else
                {
                    curTime = GlobalVar.DayIndexToTimeEx(m_TotalSigMan.CurIndex);
                }

                if (curTime < 90030)
                    return null;

                if (buyRatio > sellRatio)
                {
                    double delta = buyRatio - sellRatio;
                    if (curWave.Slope == GlobalVar.PriceUp && delta >= HogaSquareOccSysVar.MinSquareOccDelta)
                    {
                        m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalBuy, GlobalVar.SignalStateTrans, ref m_CurState);
                        m_TotalSigMan.WriteStateLog("매수로상태전환(일반)", m_LogFileName, m_CurState);
                        return m_CurState;
                    }
                }
                else if (sellRatio > buyRatio)
                {
                    double delta = sellRatio - buyRatio;
                    if (curWave.Slope == GlobalVar.PriceDown && delta >= HogaSquareOccSysVar.MinSquareOccDelta)
                    {
                        m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalSell, GlobalVar.SignalStateOver, ref m_CurState);
                        m_TotalSigMan.WriteStateLog("매도로상태전환(일반)", m_LogFileName, m_CurState);
                        return m_CurState;
                    }
                }
            }

            if (lastState == null)
                return null;

            /*
            // 먼저 청산을 고려해 준다.
            if (lastState.Type == GlobalVar.SignalBuy)
            {
                double deltaHigh = m_TotalSigMan.GetDayHigh() - curVal;
                if (deltaHigh > HogaSquareOccSysVar.MinLiquidVal)
                {
                    // 매수 청산
                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalExitBuy, GlobalVar.SignalStateLiquid, ref m_CurState);
                    m_TotalSigMan.WriteStateLog("매수청산", m_LogFileName, m_CurState);
                    return m_CurState;
                }
            }
            else if (lastState.Type == GlobalVar.SignalSell)
            {
                double deltaLow = curVal - m_TotalSigMan.GetDayLow();
                if (deltaLow > HogaSquareOccSysVar.MinLiquidVal)
                {
                    // 매도 청산
                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalExitSell, GlobalVar.SignalStateLiquid, ref m_CurState);
                    m_TotalSigMan.WriteStateLog("매도청산", m_LogFileName, m_CurState);
                    return m_CurState;
                }
            }*/

            if (buyRatio > sellRatio)
            {
                double delta = buyRatio - sellRatio;
                if (lastState.Type == GlobalVar.SignalSell && curWave.Slope == GlobalVar.PriceUp && delta > HogaSquareOccSysVar.MinSquareOccDelta)
                {
                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalBuy, GlobalVar.SignalStateTrans, ref m_CurState);
                    m_TotalSigMan.WriteStateLog("매수로상태전환(일반)", m_LogFileName, m_CurState);
                    return m_CurState;
                }
            }
            else if (sellRatio > buyRatio)
            {
                double delta = sellRatio - buyRatio;
                if (lastState.Type == GlobalVar.SignalBuy && curWave.Slope == GlobalVar.PriceDown && delta > HogaSquareOccSysVar.MinSquareOccDelta)
                {
                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalSell, GlobalVar.SignalStateOver, ref m_CurState);
                    m_TotalSigMan.WriteStateLog("매도로상태전환(일반)", m_LogFileName, m_CurState);
                    return m_CurState;
                }
            }

            return null;
        }
        // 상태를 바탕으로 신호를 발생시킨다.
        private void CheckSignal()
        {
            if (HogaSquareOccSysVar.LastSignalFired == true)
                return;
            // 먼저 상태 개수를 확인한다.
            // 정해진 상태 개수 안에서만 신호를 발생시킨다.
            int stateCount = m_PriceStateList.Count;
            if (stateCount < HogaSquareOccSysVar.SysStartState ||
                stateCount > HogaSquareOccSysVar.SysEndState)
                return;

            // 먼저 청산을 확인한다.
            // 가격에 의한 청산 신호가 있는지 확인한다.
            EasyTrader.Signal.PriceSignal curSignal = GetLiquidSignalByTotalPrice();
            EasyTrader.Signal.PriceSignal activeSignal = null;
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                HogaSquareOccSysVar.AutoOrder = false;
                HogaSquareOccSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(HogaSquareOccSysVar.AutoOrder, GlobalVar.SysTypeHogaSquareOcc);
            }

            curSignal = GetLiquidSignalByMaxPrice();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                HogaSquareOccSysVar.AutoOrder = false;
                HogaSquareOccSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(HogaSquareOccSysVar.AutoOrder, GlobalVar.SysTypeJisuWaveHogaSummit);
            }

            curSignal = GetLiquidSignalByTotalPriceStepByStep();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                // 단계별 총 청산액을 증가시켜 준다.
                HogaSquareOccSysVar.TotalProfitStepLiquidVal += HogaSquareOccSysVar.StepLiquidVal;
            }

            curSignal = GetLiquidSignalByStateCountStepByStep();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                // 단계별 상태값을 증가시켜 준다.
                HogaSquareOccSysVar.StepLiquidStateCount++;
            }

            curSignal = GetLiquidSignalByPerPrice();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
            }
            // 시간에 의한 청산 신호가 있는지 확인한다.
            curSignal = GetLiquidSignalByTime();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                HogaSquareOccSysVar.AutoOrder = false;
                HogaSquareOccSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(HogaSquareOccSysVar.AutoOrder, GlobalVar.SysTypeHogaSquareOcc);
            }
            // 상태 개수에 의한 청산 신호가 있는지 확인한다.
            curSignal = GetLiquidSignalByStateCount();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                HogaSquareOccSysVar.AutoOrder = false;
                HogaSquareOccSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(HogaSquareOccSysVar.AutoOrder, GlobalVar.SysTypeHogaSquareOcc);
            }
            // 상태 전환에 의한 신호가 있는지 확인한다.
            curSignal = GetSignalByStateChange();
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
            }
        }

        public void UpdateSysState()
        {
            FindCurState();
            CheckSignal();
        }
    }
}
